package encrypt

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"errors"
)

var pwdKey =[]byte("DIS**#KKKDJJSKDI")

// aes
// 16,24,32  对应 AES-128,AES-192,AES-256,

// PKCS7 填充模式  cipherText的数量不足blockSize 时进行填充
func PKCS7Padding(cipherText []byte,blockSize int) []byte {
	// 计算需要填充的数量和填充数
	padding := blockSize - len(cipherText)%blockSize
	// Repeat 把切片复制 padding 个并合并成一个切片
	padText := bytes.Repeat([]byte{byte(padding)},padding)
	//fmt.Println("aaaa",padText)
	return append(cipherText,padText...)
}

// 填充的反向操作,删除填充的字符串
func PKCS7UnPadding(origData []byte) ([]byte, error) {
	length := len(origData)
	if length == 0 {
		return nil,errors.New("加密字符串错误!")
	} else {
		// 获取填充字符串长度
		unpadding := int(origData[length - 1])
		// 截取切片,删除填充字节,并返回明文
		return origData[:(length - unpadding)],nil
	}
}

// Aes 加密
func AesEcrypt(originData []byte,key [] byte) (end []byte,err error) {
	// 创建加密算法实例
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	// 获取块大小
	blockSize := block.BlockSize()
	// 对数据进行填充
	originData = PKCS7Padding(originData,blockSize)
	// 采用 AES 加密方法中 CBC加密模式
	blockMode := cipher.NewCBCEncrypter(block,key[:blockSize])
	crypted := make([]byte,len(originData))
	blockMode.CryptBlocks(crypted,originData)
	return crypted,nil
}

// Aes 解密
func AesDeCrypt(cypted []byte, key []byte) ([]byte, error) {
	// 创建加密算法实例
	block,err := aes.NewCipher(key)
	if err != nil {
		return nil,err
	}
	// 获取块大小
	blockSize := block.BlockSize()
	// 创建加密客户端
	blockMode := cipher.NewCBCDecrypter(block,key[:blockSize])
	originData := make([]byte,len(cypted))
	// 这个函数可以进行解密和解密
	blockMode.CryptBlocks(originData,cypted)
	// 去除填充字符串
	originData,err = PKCS7UnPadding(originData)
	if err != nil {
		return nil,err
	}
	return originData,nil
}

// base64 在加密一次
func EnPwdCode(pwd []byte) (string,error) {
	result,err := AesEcrypt(pwd,pwdKey)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(result),err
}

// base64 解密
func DePwdCode(pwd string) ([]byte, error) {
	pwdByge,err :=  base64.StdEncoding.DecodeString(pwd)
	if err != nil {
		return nil,err
	}
	return AesDeCrypt(pwdByge,pwdKey)

}

